import Foundation
import Thrift
import ThriftSwiftNio

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import Dispatch

let logQueue = DispatchQueue(label: "log", qos: .background, attributes: .concurrent)
let pQueue = DispatchQueue(label: "log", qos: .userInitiated, attributes: .concurrent)

class TPerfectServer<InProtocol: TProtocol, OutProtocol: TProtocol> {

 private var server = HTTPServer()
 //private var server = TCPServer()

 private var processor: TProcessor

 init(address: String? = nil,
      path: String? = nil,
      port: Int,
      processor: TProcessor,
      inProtocol: InProtocol.Type,
      outProtocol: OutProtocol.Type) throws {

   self.processor = processor

   if let address = address {
     server.serverAddress = address
   }
   server.serverPort = UInt16(port)

   var routes = Routes()
   var uri = "/"
   if let path = path {
     uri += path
   }
   routes.add(method: .post, uri: uri) { request, response in
     pQueue.async {
       response.setHeader(.contentType, value: "application/x-thrift")

       let itrans = TMemoryBufferTransport()
       if let bytes = request.postBodyBytes {
         let data = Data(bytes: bytes)
         itrans.reset(readBuffer: data)
       }

       let otrans = TMemoryBufferTransport(flushHandler: { trans, buff in
         let array = buff.withUnsafeBytes {
           Array<UInt8>(UnsafeBufferPointer(start: $0, count: buff.count))
         }
         response.status = .ok
         response.setBody(bytes: array)
         response.completed()
       })

       let inproto = InProtocol(on: itrans)
       let outproto = OutProtocol(on: otrans)

       do {
         try processor.process(on: inproto, outProtocol: outproto)
         try otrans.flush()
       } catch {
         response.status = .badRequest
         response.completed()
       }
     }
   }
   server.addRoutes(routes)
 }

 func serve() throws {
   try server.start()
 }
}

class TestServiceHandler : TestService {
    func Hello(HelloString: String) throws -> String {
        return "Hello " + HelloString
    }

    func GetSampleStruct(key: Int32, value: String) throws -> SampleStruct {
        return SampleStruct(key: key, value: value)
    }
}

class TestProcessor : Processor {
   func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws {
       print("In process")

       let handler = TestServiceHandler()

       let processor = TestServiceProcessor(service: handler)

       do {
           try processor.process(on: inProtocol, outProtocol: outProtocol)
       }
       catch {
           print("Error in process")
       }

       print("Response sent back")
   }
}

 //let processor = TestProcessor()

//let server = Server(host: "127.0.0.1", port: 9091, with: processor, inProtocolType: TBinaryProtocol.self, outProtocolType: TBinaryProtocol.self)

// let processor = Processor(service: self.serviceHandler)
// processor.process(on: inproto, outProtocol: outproto)

let server = try? TSocketServer(port: 9091,
                                 service: MyConcreteService(), // your implementation of thrift service
                                 inProtocol: TBinaryProtocol.self,
                                 outProtocol: TBinaryProtocol.self,
                                 processor: MyServiceProcessor.self) // generated service processor


 server.run()

  print("Server closed")




//let server = try? TPerfectServer(port: 9090,
//                                processor: TestServiceProcessor(service: TestServiceHandler()),
//                                inProtocol: TBinaryProtocol.self,
//                                outProtocol: TBinaryProtocol.self)
//
//try? server?.serve()


